home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Code Resources / Jims CDEFs 1.50 / CDEF Source / source / cdefGBox.c < prev    next >
Encoding:
Text File  |  1995-11-08  |  14.9 KB  |  489 lines  |  [TEXT/KAHL]

  1. //------------------------- © 1991-1995 by James G. Stout --------------------------
  2. // File        : cdefGBox.c
  3. // Date        : September 1,1991
  4. // Author    : Jim Stout
  5. //             :
  6. // Purpose    : "Group Box" CDEF
  7. //             : A very simple CDEF that draws a titled box. It supports
  8. //             : 3 variations - grayLine, ctl3D, insetBox, and useWindFont (1,2, 4 & 8)
  9. //             :
  10. //             : Pretty straight forward code here, only trick here is to use the 
  11. //             : contrlMax value as the height of the control.  This is done to keep
  12. //             : the Control Manager from thinking the control overlays the controls
  13. //             : you want inside the GroupBox.  Set the real control rect to some value
  14. //             : sufficient to see the title in your resource editor and set contrlMax
  15. //             : to the height of the box you want drawn.
  16. //            :
  17. // ** IMPORTANT INFORMATION **
  18. //            :
  19. //            : Since the Control Manager doesn't know about the extra drawing done
  20. //            : by this control, some extra handling is required for update events.
  21. //            : Just calling UpdtControl() will not suffice since there could be a
  22. //            : portion of this control that needs to be drawn that is outside the
  23. //            : "official" control rect.
  24. //            :
  25. //            : So, make sure you call Draw1Control() in response to an update for
  26. //            : any control that uses this CDEF.  Calling DrawControls is ok too, but
  27. //            : will draw all of the controls in the window.
  28. //            :
  29. //            : If you find a use for this, I'd love to know about it.  Bug reports
  30. //            : are always interesting.
  31. //            :
  32. //            : Internet    : JimS@WRQ.COM(work hours, PST)
  33. //            : AppleLink   : WRQ            (daily)
  34. //            : CompuServe  : 73240,2052    (weekly or so)
  35. //            : AOL         : JasG        (weekly or so)
  36. //            : eWorld      : Jim Stout    (weekly or so)
  37. //----------------------------------------------------------------------------------
  38. //#define _DEBUGCDEF
  39.  
  40. #include "fatCDEF.h"
  41.  
  42. #include <Controls.h>
  43. #include <LowMem.h>
  44. #include <Memory.h>
  45. #include <ToolUtils.h>
  46. #include <Types.h>
  47.  
  48. #include "colorCDEF.h"
  49. #include "grayCDEF.h"
  50. #include "miscCDEF.h"
  51.  
  52. #include "cdefGBox.h"
  53.  
  54. #ifdef _DEBUGCDEF
  55. pascal long CDmain    (short, ControlHandle, short, long);
  56.  
  57. pascal long CDmain    (short varCode, ControlHandle theCtl, short message, long param)
  58. #else
  59. //==================================================================================
  60. // CDEF entry point
  61. //==================================================================================
  62.  
  63. pascal long main    (short varCode, ControlHandle theCtl, short message, long param)
  64. #endif
  65. {
  66.     gbDataHandle    hGB;
  67.     Rect            r;
  68.     GrafPtr            thisPort;
  69.     SignedByte        cState, dState;
  70.     
  71. #include "fatEntry.c"
  72.     
  73.     cState = HGetState((Handle)theCtl);
  74.     HLock((Handle)theCtl);
  75.     if((**theCtl).contrlData) {
  76.         dState = HGetState((**theCtl).contrlData);
  77.         HLock((**theCtl).contrlData);
  78.     }
  79.     
  80.     switch(message) {
  81.     
  82.         case initCntl:
  83.             hGB = (gbDataHandle)NewHandle(sizeof(gbData));
  84.             if(hGB) {
  85.                 GetPort(&thisPort);
  86.                 (**hGB).realHt = (**theCtl).contrlMax;        // true height of control
  87.                 
  88.                 r = (**hGB).titleRect = (**theCtl).contrlRect;// we'll adjust this later
  89.                 r.bottom = r.top + (**hGB).realHt+1;        // for font size…
  90.                 r.right++;                                    // allow for 3D shadow
  91.                 
  92.                 InvalRect(&r);                                // fool ControlMgr since
  93.                                                             // since we draw outside
  94.                                                             // the true controlRect.
  95.                                                     
  96.                 (**hGB).txFont = thisPort->txFont;
  97.                 (**hGB).txSize = thisPort->txSize;
  98.                                 
  99.                 (**theCtl).contrlData = (Handle)hGB;            // save our data
  100.                 if((**theCtl).contrlData) {
  101.                     dState = HGetState((**theCtl).contrlData);
  102.                     HLock((**theCtl).contrlData);
  103.                 }
  104.             }
  105.         break;
  106.         
  107.         case dispCntl:
  108.             hGB = (gbDataHandle)(**theCtl).contrlData;
  109.             if(hGB) {
  110.                 r = (**theCtl).contrlRect;
  111.                 r.bottom = r.top + (**hGB).realHt+1;        // can't rely on Control Mgr
  112.                 r.right++;                                    // to erase our "fake" rect
  113.                 EraseRect(&r);                                // or the 3D shadow.\
  114.                 HUnlock((Handle)hGB);
  115.                 DisposeHandle((Handle)hGB);
  116.                 (**theCtl).contrlData = 0;
  117.             }
  118.         break;
  119.         
  120.         case drawCntl:
  121.             doDraw(theCtl, varCode);
  122.         break;
  123.         
  124.         case calcCRgns:
  125.             RectRgn((RgnHandle)(param & 0x7fffffffL), &(*theCtl)->contrlRect);
  126.         break;
  127.         
  128.         case calcCntlRgn:
  129.         case calcThumbRgn:
  130.             RectRgn((RgnHandle)(param), &(*theCtl)->contrlRect);
  131.         break;
  132.     }
  133.     
  134.     if((**theCtl).contrlData)
  135.         HSetState((**theCtl).contrlData, dState);
  136.     HSetState((Handle)theCtl, cState);
  137.     
  138. #include "fatExit.c"
  139.  
  140.     return (0L);                                            // this control does nothing
  141. }
  142.  
  143. //==================================================================================
  144. // If running with System 7, use DeviceLoop to gracefully handle multiple screens.
  145. // Simulate DeviceLoop if using System 6...
  146. //==================================================================================
  147.  
  148. static void doDraw(ControlHandle theCtl, short varCode)
  149. {
  150.     short                    txF, txS;
  151.     GrafPtr                    thisPort;
  152.     devLoopHandle            hDl;
  153.     Rect                    fullRect;
  154.     RgnHandle                saveClip, hRgn;
  155.     gbDataHandle            hGB;
  156.     DeviceLoopDrawingUPP    drawControlUPP;
  157.  
  158.     hGB = (gbDataHandle)(**theCtl).contrlData;
  159.     if(!hGB)
  160.         return;                                            // oops!
  161.  
  162. //----------------------------------------------------------------------------------
  163. // set window font & size info    
  164. //----------------------------------------------------------------------------------
  165.  
  166.     GetPort(&thisPort);
  167.     
  168.     if(!(varCode & useWindFont)) {                // use system font
  169.         txF = thisPort->txFont;                    // save current
  170.         txS = thisPort->txSize;
  171.         TextFont(LMGetSysFontFam());            // set system as current
  172.         TextSize(LMGetSysFontSize());
  173.     }
  174.  
  175. //----------------------------------------------------------------------------------
  176. //    Create our data handle to pass to DeviceLoop
  177. //----------------------------------------------------------------------------------
  178.  
  179.     hDl = (devLoopHandle)NewHandle(sizeof(devLoopData));
  180.     if(hDl) {
  181.         drawControlUPP = NewDeviceLoopDrawingProc(drawControl);
  182.         
  183.         (**hDl).theCtl = theCtl;
  184.         (**hDl).varCode = varCode;
  185.         
  186.         fullRect = (**theCtl).contrlRect;
  187.         fullRect.bottom = fullRect.top + (**hGB).realHt +1;
  188.         fullRect.right++;
  189.         (**hDl).controlRect = fullRect;
  190.         
  191. //----------------------------------------------------------------------------------
  192. //    Do the clip region properly.  Thanks Ari!
  193. //----------------------------------------------------------------------------------
  194.  
  195.         saveClip = NewRgn();
  196.         GetClip(saveClip);
  197.         
  198.         hRgn = NewRgn();
  199.         RectRgn(hRgn, &(**hDl).controlRect);
  200.         SectRgn(saveClip, hRgn, hRgn);
  201.         
  202.         if(EmptyRgn(hRgn)) {                                    // if empty, don't waste
  203.             DisposeRgn(saveClip);                                // time drawing...
  204.             DisposeRgn(hRgn);
  205.             return;
  206.         }        
  207.  
  208. //----------------------------------------------------------------------------------
  209. //    Call DeviceLoop to take care of our drawing
  210. //----------------------------------------------------------------------------------
  211.         
  212.         if(getOSVers() >= 0x0700) {
  213.             DeviceLoop (hRgn, drawControlUPP, (long)hDl, 0);
  214.         }
  215.         else {
  216.             sys6DeviceLoop (hRgn, drawControlUPP, (long)hDl, 0);
  217.         }
  218.  
  219.         SetClip(saveClip);                
  220.         DisposeRgn(hRgn);
  221.         DisposeHandle((Handle)hDl);
  222.         DisposeRoutineDescriptor(drawControlUPP);
  223.     }
  224. //----------------------------------------------------------------------------------
  225. // restore window font & size info    
  226. //----------------------------------------------------------------------------------
  227.  
  228.     if(!(varCode & useWindFont)) {
  229.         TextFont(txF);
  230.         TextSize(txS);
  231.     }
  232. }
  233.  
  234. //==================================================================================
  235. // as it says, the draw routine for the group box…
  236. //==================================================================================
  237. pascal void drawControl (short depth, short dFlags, GDHandle theDevice, long userData)
  238. {
  239.  
  240. #pragma unused(dFlags, theDevice)
  241.  
  242.     ControlHandle        theCtl;
  243.     short                varCode, boxType, titleWidth, titleHt;
  244.     Rect                titleRect, boxRect;
  245.     RgnHandle            rgSave, rgClip, rgTitle;
  246.     GrafPtr                thisPort;
  247.     FontInfo            f;
  248.     PenState            savePen;
  249.     RGBColor            saveFore,saveBack,grayColor;
  250.     RGBColor            rgbA = {0xAAAA, 0xAAAA, 0xAAAA};
  251.     Boolean                inColor = false, bgInColor = false, haveGray = false;
  252.     gbDataHandle        hGB;
  253.     devLoopHandle        hDl;
  254.     
  255. //----------------------------------------------------------------------------------
  256. // Can we draw?
  257. //----------------------------------------------------------------------------------
  258.  
  259.     hDl = (devLoopHandle)userData;                        // need control & varCode
  260.     if(hDl) {
  261.         theCtl = (**hDl).theCtl;
  262.         varCode = (**hDl).varCode;
  263.     }
  264.     else
  265.         return;
  266.  
  267. //----------------------------------------------------------------------------------
  268. // get our private data 
  269. //----------------------------------------------------------------------------------
  270.  
  271.     hGB = (gbDataHandle)(**theCtl).contrlData;
  272.     if(!hGB)
  273.         return;                                            // oops!
  274.  
  275.     HLock((Handle)hGB);
  276.     
  277.     (**hGB).titleRect = (**theCtl).contrlRect;
  278.     (**hGB).realHt = (**theCtl).contrlMax;                // true height of control
  279.  
  280. //----------------------------------------------------------------------------------
  281. // setup our drawing environment
  282. //----------------------------------------------------------------------------------
  283.  
  284.     GetPort(&thisPort);
  285.     GetPenState(&savePen);
  286.     PenSize(1,1);
  287.     PenPat( (ConstPatternParam) "\xff\xff\xff\xff\xff\xff\xff\xff");
  288.     
  289.     rgClip = NewRgn();
  290.     rgTitle = NewRgn();
  291.     rgSave = NewRgn();
  292.     GetClip(rgSave);
  293.  
  294.     boxType = varCode;
  295.     
  296.     if(varCode & useWindFont)
  297.         boxType ^= useWindFont;
  298.     
  299. //----------------------------------------------------------------------------------
  300. // Clear the title box at the top so that any font changes don't leave junk
  301. // lying around.
  302. //----------------------------------------------------------------------------------
  303.  
  304.     if((thisPort->txFont != (**hGB).txFont) ||            // if font changed,
  305.         (thisPort->txSize != (**hGB).txSize)) {            // clear rect to erase
  306.         (**hGB).txFont = thisPort->txFont;                // old font
  307.         (**hGB).txSize = thisPort->txSize;
  308.         EraseRect(&(**hGB).titleRect);                    // clear previous rect    
  309.     }
  310.     
  311.     GetFontInfo(&f);                                    // get font metrics        
  312.     titleRect = (**hGB).titleRect;                        // calc new title rect
  313.     titleRect.bottom = titleRect.top + 
  314.                         f.ascent + f.descent;
  315.     (**hGB).titleRect = titleRect;                        // save new title rect
  316.     
  317.     f.ascent+=1;                                        // fudge a bit so the
  318.     titleRect.bottom = titleRect.top + 2*(f.ascent/2);    // title lines up
  319.     titleHt = titleRect.bottom-titleRect.top;            // nicely…
  320.  
  321. //----------------------------------------------------------------------------------
  322. // calculate the real rect for the control
  323. //----------------------------------------------------------------------------------
  324.     
  325.     boxRect = (**hGB).titleRect;
  326.     boxRect.bottom = boxRect.top + (**hGB).realHt;        // full control rect    
  327.     boxRect.top+=titleHt/2;                                // box halves title area
  328.     
  329. //----------------------------------------------------------------------------------
  330. // do color checks
  331. //----------------------------------------------------------------------------------
  332.  
  333.     if(depth > 1 && !(((CGrafPtr)thisPort)->portVersion & 0x8000))
  334.         depth = 1;
  335.     if(depth > 2) {                                        // yes…
  336.         inColor = true;
  337.         saveColors(&saveFore, &saveBack);
  338.         setPartColor(theCtl, cFrameColor, true);
  339.         if((**theCtl).contrlHilite == 0xFF) {            // inactive control
  340.             haveGray = getGray(&grayColor);
  341.         }
  342.         bgInColor = true;
  343.         if(saveBack.red == 65535 &&                        // is bg white?
  344.             saveBack.green == 65535 &&
  345.             saveBack.blue == 65535)
  346.             bgInColor = false;                            // no 3D effects
  347.     }
  348.         
  349. //----------------------------------------------------------------------------------
  350. // Draw the control title
  351. //----------------------------------------------------------------------------------
  352.     titleWidth = StringWidth((*theCtl)->contrlTitle) + 10;
  353.     
  354.     if(titleWidth > 10) {                                // i.e. we have a title    
  355.         titleRect.left += 10;
  356.         titleRect.right = titleRect.left + titleWidth;
  357.         if(inColor) {
  358.             if(bgInColor && varCode & ctl3D) {            // do 3D stuff
  359.                 ForeColor(whiteColor);
  360.                 MoveTo(titleRect.left + 6,boxRect.top+titleHt/2-f.leading+1);
  361.                 DrawString((*theCtl)->contrlTitle);        // embossed title in white    
  362.             }
  363.             setPartColor(theCtl, cTextColor, true);        // get fgColor
  364.         
  365.             if(haveGray) {                                // must be inactive
  366.                 getGray(&grayColor);                    // grayed cTextColor
  367.                 RGBForeColor(&grayColor);
  368.             }
  369.         }
  370.     
  371.         MoveTo(titleRect.left + 5,boxRect.top+titleHt/2-f.leading);
  372.         DrawString((*theCtl)->contrlTitle);                // draw the title in fgColor
  373.         
  374. //
  375. //    watch carefully!  To keep the frame from drawing through the title text, set
  376. //    a clip region that excludes the title rect
  377. //
  378.         RectRgn(rgTitle, &titleRect);
  379.         DiffRgn(rgSave, rgTitle, rgClip);
  380.         SetClip(rgClip);            
  381.     }
  382.         
  383. //----------------------------------------------------------------------------------
  384. // draw the group box frame
  385. //----------------------------------------------------------------------------------
  386.  
  387.     if(varCode & grayLine) {
  388.         PenPat( (ConstPatternParam) "\x55\xAA\x55\xAA\x55\xAA\x55\xAA");
  389.     }
  390.     
  391.     switch(boxType) {
  392.         case 2:
  393.         case 3:
  394.             if(inColor) {
  395.                 ForeColor(whiteColor);
  396.                 OffsetRect(&boxRect, 1, 1);
  397.                 FrameRect(&boxRect);                    // white shadow
  398.                 OffsetRect(&boxRect, -1, -1);
  399.                 RGBForeColor(&saveFore);
  400.                 FrameRect(&boxRect);
  401.             }
  402.             else
  403.                 FrameRect(&boxRect);
  404.         break;
  405.         case 5:
  406.         case 7:
  407.             PenPat( (ConstPatternParam) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF");
  408.             if(inColor) {
  409.                 boxRect.left++;
  410.                 FrameRect(&boxRect);
  411.                 RGBForeColor(&rgbA);                    // slight 3D effect
  412.                 MoveTo(boxRect.left-1,boxRect.bottom);
  413.                 LineTo(boxRect.left-1,boxRect.top-1);
  414.                 LineTo(boxRect.right,boxRect.top-1);
  415.                 ForeColor(whiteColor);
  416.                 LineTo(boxRect.right, boxRect.bottom);
  417.                 LineTo(boxRect.left, boxRect.bottom);
  418.             }
  419.             else
  420.                 FrameRect(&boxRect);
  421.         break;
  422.     }
  423.  
  424.     
  425.     if(inColor) {    
  426.         setPartColor(theCtl, cFrameColor, true);        // groupBox color
  427.         
  428.         if((**theCtl).contrlHilite == 0xFF) {            // inactive control
  429.             haveGray = getGray(&grayColor);
  430.             if(haveGray)                                // grayed cFrameColor
  431.                 RGBForeColor(&grayColor);
  432.         }
  433.     }
  434.     
  435.     switch(boxType) {
  436.         case 0:
  437.         case 1:
  438.         case 2:
  439.         case 5:
  440.         case 7:
  441.             FrameRect(&boxRect);                        // frame the groupbox
  442.         break;
  443.         case 4:
  444.         case 6:
  445.             if(bgInColor) {
  446.                 ForeColor(whiteColor);
  447.                 MoveTo(boxRect.right, boxRect.top);
  448.                 LineTo(boxRect.right, boxRect.bottom);
  449.                 LineTo(boxRect.left, boxRect.bottom);
  450.                 setPartColor(theCtl, cFrameColor, true);
  451.                 getGray(&grayColor);
  452.                 RGBForeColor(&grayColor);
  453.                 LineTo(boxRect.left, boxRect.top);
  454.                 LineTo(boxRect.right, boxRect.top);
  455.             }
  456.             else
  457.                 FrameRect(&boxRect);
  458.         break;
  459.     }
  460.  
  461.     SetClip(rgSave);
  462.     DisposeRgn(rgSave);
  463.     DisposeRgn(rgClip);
  464.     DisposeRgn(rgTitle);
  465.  
  466. //----------------------------------------------------------------------------------
  467. // gray out the old, System 6 way if we didn't get a gray color
  468. //----------------------------------------------------------------------------------
  469.  
  470.     if(!haveGray && (**theCtl).contrlHilite == 0xFF) {    // no gray but inactive
  471.         
  472.         PenPat( (ConstPatternParam) "\xAA\x55\xAA\x55\xAA\x55\xAA\x55");
  473.         PenMode(patBic);
  474.         FrameRect(&boxRect);                            // gray the groupbox
  475.         PaintRect(&(**hGB).titleRect);                    // gray the title
  476.     }
  477.         
  478. //----------------------------------------------------------------------------------
  479. // restore drawing environment
  480. //----------------------------------------------------------------------------------
  481.  
  482.     if(inColor) {
  483.         restoreColors(&saveFore, &saveBack);
  484.     }
  485.     
  486.     SetPenState(&savePen);
  487.  
  488.     HUnlock((Handle)hGB);
  489. }